﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace mid
{
    public partial class Form1 : Form
    {
        private Socket server;
        private Socket RemoteClient;
        private Socket ClientReturn;
        private byte[] data = new byte[1024];
        private byte[] datars = new byte[1024];
        private int connections = 0;

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            txtConnectionStatus.Enabled = false;
            txtDataRecieved.Enabled = false;
            txtDataSent.Enabled = false;
            btnConnect.Enabled = false;
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                btnConnect.Enabled = false;
                RemoteClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint remoteEPoint = new IPEndPoint(IPAddress.Parse(txtIPAddress.Text), 2000);
                RemoteClient.BeginConnect(remoteEPoint, new AsyncCallback(OnConnectedRemote), null);
            }
            catch
            {
                CloseConnection();
            }

        }

        void OnConnectedRemote(IAsyncResult result)
        {
            try
            {
                RemoteClient.EndConnect(result);
            }
            catch
            {
                CloseConnection();
            }
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            try
            {
                server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                int port;
                port = int.Parse(txtPortNo.Text);
                IPEndPoint localEP = new IPEndPoint(0, port);
                server.Bind(localEP);
                server.Listen(4);

                server.BeginAccept(new AsyncCallback(OnConnected), null);
                btnStartServer.Enabled = false;
                txtConnectionStatus.Text = "Waiting for client .....";
                btnConnect.Enabled = true;
                txtIPAddress.Enabled = false;
                txtPortNo.Enabled = false;
            }
            catch
            {
                MessageBox.Show("Please check your Server!");
            }
        }

        void OnConnected(IAsyncResult result)
        {
            Socket client = server.EndAccept(result);
            connections++;
            server.BeginAccept(new AsyncCallback(OnConnected), null);

            try
            {
                txtConnectionStatus.Text = "" + connections;
                byte[] message = Encoding.ASCII.GetBytes("Welcome to my server");
                client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnDataSent), client);
            }
            catch (SocketException)
            {
                CloseClient(client);
            }
        }

        void OnDataSent(IAsyncResult result)
        {
            Socket client = (Socket)result.AsyncState;

            try
            {
                int sent = client.EndSend(result);
                client.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);
            }
            catch (SocketException)
            {
                CloseClient(client);
            }

        }

        // Received from CLIENT and Sent to SERVER
        void OnDataReceived(IAsyncResult result)
        {
            Socket client = (Socket)result.AsyncState;
            ClientReturn = (Socket)result.AsyncState;
            
            try
            {
                int receive = client.EndReceive(result);
                
                if (receive == 0)
                {
                    CloseClient(client);
                    return;
                }
                else
                {
                    string message = Encoding.ASCII.GetString(data, 0, receive);
                    txtDataSent.Text = message;
                    lbxText.Items.Add(message);
                    txtDataRecieved.Text = message;

                    if (txtIPAddress.Text != "Disconnected" || txtIPAddress.Text != "") //|| text-Box1.Text == txtMCPortN.Text)
                    {
                        string messageRec = message;// +"Received" + DateTime.Now.ToShortTimeString();
                        byte[] echomessage = Encoding.ASCII.GetBytes(messageRec);
                        //client.BeginSend(datars, 0, datars.Length, SocketFlags.None, new AsyncCallback(OnDataSent), client);
                        RemoteClient.BeginSend(echomessage, 0, echomessage.Length, SocketFlags.None, new AsyncCallback(OnRemoteDataSent), null);
                    }
                    else
                    {
                        //string message = Encoding.ASCII.GetString(data, 0, receive);
                        //listBox1.Items.Add(message);
                        //textBox3.Text = message;
                        //byte[] echomessage = Encoding.ASCII.GetBytes(message);
                        //client.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);                        
                        return;
                    }
                }
            }
            catch (SocketException)
            {
                CloseClient(client);
            }
        }

        void OnRemoteDataSent(IAsyncResult result)
        {
            try
            {
                int sent = RemoteClient.EndSend(result);
                RemoteClient.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(OnRemoteDataReceived), null);
            }
            catch (SocketException)
            {
                CloseConnection();
            }
        }

        void OnRemoteDataReceived(IAsyncResult result)
        {
            try
            {
                int receive = RemoteClient.EndReceive(result);
                string message = Encoding.ASCII.GetString(data, 0, receive);
                datars = Encoding.ASCII.GetBytes(message);
                ClientReturn.BeginSend(datars, 0, datars.Length, SocketFlags.None, new AsyncCallback(OnDataSent), ClientReturn);
            }
            catch (Exception)
            {
                CloseConnection();
            }
        }

        void OnDataSentBack(IAsyncResult result)
        {
            Socket client = (Socket)result.AsyncState;
            try
            {
                int sent = client.EndSend(result);           
            }
            catch (SocketException)
            {
                CloseClient(client);
            }
        }

        public void CloseClient(Socket client)
        {
            client.Close();

            connections--;

            txtConnectionStatus.Text = "" + connections;
        }

        public void CloseConnection()
        {
            //client.Close(); //close client connection
            txtConnectionStatus.Text = "Disconnected  ...";
            btnStartServer.Enabled = true; // disappear connect button
            btnConnect.Enabled = false;
        }
    }
}